package com.ala4.oxcafe.boot.async;

import com.ala4.oxcafe.boot.ExcelExport;
import com.ala4.oxcafe.boot.repository.ExportTaskDTO;
import com.ala4.oxcafe.boot.utils.ThreadPoolUtil;
import com.ala4.oxcafe.common.utils.id.IdUtil;
import com.ala4.oxcafe.enums.AsyncTaskStateEnum;
import com.ala4.oxcafe.export.ExportPage;
import com.ala4.oxcafe.export.ExportResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.concurrent.Future;

/**
 * 异步导出处理
 *
 * @author PING
 * @version 1.0.0
 * @date 2025/8/1 16:45
 */
@Slf4j
@Service
//@AllArgsConstructor
public class AsyncExportService {

    /**
     * 使用spring自带的异步任务线程池
     */
    private final ThreadPoolTaskExecutor threadPoolTaskExecutor;

    /**
     * 异步导出任务处理器-可以查看所有正在进行的异步导出任务
     */
    private final ExportFutureManager exportFutureManager;

    /**
     * 导出模板
     */
    private final ExportAsyncTemplate exportAsyncTemplate;


    public AsyncExportService(ExportFutureManager exportFutureManager, ExportAsyncTemplate exportAsyncTemplate) {
        // 在构造函数中初始化
        threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        // 配置线程池
        OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
        // 获取CPU核心数量
        int cores = osBean.getAvailableProcessors();
        threadPoolTaskExecutor.setCorePoolSize(2); // 核心线程数
        threadPoolTaskExecutor.setMaxPoolSize(5); // 最大线程数
        threadPoolTaskExecutor.setQueueCapacity(10); // 队列容量
        threadPoolTaskExecutor.setThreadNamePrefix("AsyncExport-"); // 线程名前缀
        threadPoolTaskExecutor.initialize(); // 必须初始化

        this.exportFutureManager = exportFutureManager;
        this.exportAsyncTemplate = exportAsyncTemplate;
    }

    /**
     * 创建异步导出任务
     *
     * @param exportResult 第一页的返回数据
     * @param target       target
     * @param method       method
     * @param args         args
     * @param exportPage   分页参数
     * @param excelExport  导出注解
     */
    public void asyncExportAndResponse(Object target, Method method, Object[] args,
                                       ExportPage exportPage, ExportResult exportResult, ExcelExport excelExport) {

        // 创建一个异步任务的落库DTO
        ExportTaskDTO exportTaskDTO = this.createExportTaskDTO(excelExport.excelName());

        // 触发到导出模版的逻辑
        exportAsyncTemplate.submit(exportTaskDTO, () -> {

            // 提交一个异步任务到线程池
            Future<?> submit = threadPoolTaskExecutor.submit(new AsyncExportTaskRunnable(target, method, args,
                    exportResult, exportPage, excelExport,
                    exportTaskDTO, exportAsyncTemplate, exportFutureManager));

            // 异步任务提交到异步管理器
            exportFutureManager.put(exportTaskDTO.getTaskCode(), submit);

            return exportTaskDTO.getTaskCode();
        });

    }

    /**
     * 返回线程池是否可以继续提交任务
     *
     * @return true=可以提交, false=不可提交（将触发拒绝策略）
     */
    public boolean canAcceptTask() {
        log.info("{}:{}", threadPoolTaskExecutor.getThreadNamePrefix(), ThreadPoolUtil.getPoolStats(threadPoolTaskExecutor));
        return ThreadPoolUtil.canAcceptTask(threadPoolTaskExecutor);
    }

    private ExportTaskDTO createExportTaskDTO(String excelName) {
        ExportTaskDTO dto = new ExportTaskDTO();
        dto.setTaskCode(IdUtil.objectId());
        dto.setTaskName(excelName);
        dto.setHostName("");
        dto.setServiceName("");
        dto.setTenantId(0L);
        dto.setUserId(0L);
        dto.setState(AsyncTaskStateEnum.WAITING);
        dto.setUserId(0L);
        dto.setCreateBy("loginUser.getUsername()");
        dto.setCreateTime(LocalDateTime.now());
        dto.setUpdateBy("loginUser.getUsername()");
        dto.setUpdateTime(LocalDateTime.now());
        return dto;
    }
}
